<?PHP
use \Exception;
final class Router
{
    const GET = 1;
    const PUT = 2;
    const POST = 4;
    const DELETE = 8;
    public $debug = false;
    private $type;
    private $controller_dir;
    private $source;
    private $error = array();
    public function __construct($controller_dir)
    {
        $this->controller_dir = $controller_dir;
        $this->type = strtoupper($_SERVER['REQUEST_METHOD']);
        switch ($this->type)
        {
            case 'GET':
            case 'DELETE':
                $this->source = $_GET;
                break;
            case 'PUT':
                parse_str(file_get_contents('php://input'), $this->source);
                break;
            case 'POST':
                $this->source = $_POST;
            default:/*empty*/
        }
        //保留$_GET,$_POST廣域變數
        //unset($_GET);
        $_GET = array('透過API所以$_GET被移除了,原始GET資料為'.print_r($_GET,1));
        //unset($_POST);
        $_POST = array('透過API所以$_POST被移除了,原始POST資料為'.print_r($_POST,1));
        unset($_REQUEST);
    }
    
    ///例外處理
    final public function onException(Exception $e)
    {
        $this->error = array(
            'msg'=>$e->getMessage(),
            'code'=>$e->getCode(),
            'file'=>$e->getFile(),
            'line'=>$e->getLine()
        );
    }
    
    ///錯誤處理
    final public function onError($errno, $errstr, $errfile=NULL, $errline=NULL, array $errcontext=array())
    {
        $this->error = array(
            'errno'=>$errno,
            'msg'=>$errstr,
            'file'=>$errfile,
            'line'=>$errline
        );
    }
    public function &getSource()
    {
        return $this->source;
    }
    public function execute($ctrl, $handle)
    {
        set_exception_handler(array($this,'onException'));
        if ($this->debug)
        {
            set_error_handler(array($this,'onError'));
        }
        if ( ! preg_match('/^\/?\w+(\/\w+)*$/', $ctrl))
        {
            $this->error[] = "不允許的類別名稱";
        }
        if ( ! preg_match('/^\w+$/', $handle))
        {
            $this->error[] = "不允許的方法名稱";
        }
        if (empty($this->error))
        {
            $file = $this->controller_dir . DIRECTORY_SEPARATOR . $ctrl . '.php';
            if (is_readable($file))
            {
                require_once $file;
                if (is_callable(array($ctrl, $handle)))
                {
                    try{
                        $retval = $ctrl::$handle($this->type, $this->source);
                    }
                    catch (Exception $e)
                    {
                        $this->onException($e);
                    }
                    if (empty($this->error))
                    {
                        return (array)$retval;
                    }
                }
                else
                {
                    $this->error[] = "controller[{$ctrl}] 沒有 [{$handle}] 靜態方法";
                }
            }
            else
            {
                $this->error[] = "找不到檔案[{$file}]";
            }
        }
        return array(
            'ret'=>NULL,
            'result'=>false,
            'request_method'=>$this->type,
            'msg'=>'無程序可供使用',
            'error'=>$this->error
        );
    }
}